package com.xbongbong.saas.help.workflow;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.contract.pojo.dto.ContractUpdateDTO;
import com.xbongbong.pro.contract.pojo.dto.ContractUpdateWhenOutstockDTO;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.product.pojo.ProductSavePojo;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockUpdateEntity;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.InventoryEntityExt;
import com.xbongbong.saas.domain.entity.ext.ReturnedPurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.TransferEntityExt;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.ReturnedPurchaseStatusEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.business.WaitOutStockStatusEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.dictionary.AllOutBoundEnum;
import com.xbongbong.saas.enums.dictionary.ExpressStatusEnum;
import com.xbongbong.saas.enums.dictionary.InventoryNewStatusEnum;
import com.xbongbong.saas.enums.dictionary.InventoryStatusEnum;
import com.xbongbong.saas.enums.dictionary.ReturnedStatusEnum;
import com.xbongbong.saas.enums.dictionary.ShipStatusEnum;
import com.xbongbong.saas.enums.dictionary.TransferNewStatusEnum;
import com.xbongbong.saas.enums.dictionary.WorkOrderShipStatusEnum;
import com.xbongbong.saas.enums.product.OutstockProductEnum;
import com.xbongbong.saas.help.BatchKeyHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.InventoryModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.ProductionOrderModel;
import com.xbongbong.saas.model.ReturnedPurchaseModel;
import com.xbongbong.saas.model.TransferModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @author 魏荣杰
 *
 */
@Component
public class OutstockHelp {

    @Resource
    private ReturnedPurchaseModel returnedPurchaseModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private InventoryModel inventoryModel;
    @Resource
    private TransferModel transferModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private ProductionOrderModel productionOrderModel;
    @Resource
    private ReturnedPurchaseHelp returnedPurchaseHelp;
    @Resource
    private ContractHelp contractHelp;
    @Resource
    private TransferHelp transferHelp;
    @Resource
    private WorkOrderHelp workOrderHelp;
    @Resource
    private ProductionOrderHelp productionOrderHelp;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private ContractProductModel contractProductModel;


    public void setOutstockDocumentsNew(String corpid, JSONObject data, Integer distributorMark, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long outstockId = paasFormDataEntity.getId();
        Long refId = data.getLong(OutstockEnum.REF_ID.getAttr());
        Integer outstockType = FastJsonHelper.getIntegerFromFormData(data, OutstockEnum.TYPE.getAttr());
        OutstockTypeEnum outstockTypeEnum = OutstockTypeEnum.getByCode(outstockType);
        JSONArray productJsonArray = paasFormDataEntity.getData().getJSONArray(InstockEnum.PRODUCT.getAttr());
        List<ProductSavePojo> productSavePojoList = new ArrayList<>();
        productJsonArray.forEach(item -> {
            JSONObject json = (JSONObject) item;
            ProductSavePojo productSavePojo = new ProductSavePojo();
            productSavePojo.setId(json.getLong(OutstockProductEnum.PRODUCT.getAttr()));
            productSavePojo.setNum(json.getDouble(OutstockProductEnum.NUM.getAttr()));
            if (Objects.nonNull(json.getLong(BusinessConstant.REF_PRODUCT_ID))) {
                productSavePojo.setRefProductId(json.getLong(BusinessConstant.REF_PRODUCT_ID));
            }
            productSavePojoList.add(productSavePojo);
        });
        PaasFormDataEntityExt paasFormDataEntityExt;
        switch (outstockTypeEnum){
            case RETURNED_PURCHASE_OUTSTOCK:
                paasFormDataEntityExt = returnedPurchaseModel.getByKey(refId, corpid);
                if (Objects.isNull(paasFormDataEntityExt)) {
                    return;
                }
                ReturnedPurchaseEntityExt returnedPurchaseEntityExt = new ReturnedPurchaseEntityExt();
                BeanUtil.copyProperties(paasFormDataEntityExt,returnedPurchaseEntityExt);
                JSONObject returnedPurchaseData = returnedPurchaseEntityExt.getData();
                //returnedPurchaseData.put(ReturnedPurchaseEnum.OUTSTOCK_ID.getAttr(), outstockId);
                //returnedPurchaseData.put(ReturnedPurchaseEnum.STATUS.getAttr(), ReturnedPurchaseStatusEnum.OUTSTOCK.getStatus());
                boolean allOutBound = returnedPurchaseHelp.judgeReturnPurchaseAllOutBound(outstockId,refId,corpid,productSavePojoList);
                returnedPurchaseData.put(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr(), ReturnedStatusEnum.DELIVERED.getCode());
                if (allOutBound){
                    returnedPurchaseData.put(ReturnedPurchaseEnum.RETURNED_STATUS.getAttr(),ReturnedStatusEnum.RETURNED.getCode());
                    returnedPurchaseData.put(ReturnedPurchaseEnum.OUTSTOCK_ID.getAttr(), AllOutBoundEnum.ALL_OUT.getCode());
                    returnedPurchaseData.put(ReturnedPurchaseEnum.STATUS.getAttr(), ReturnedPurchaseStatusEnum.OUTSTOCK.getStatus());
                }/* else {
                    returnedPurchaseData.put(ReturnedPurchaseEnum.OUTSTOCK_ID.getAttr(), "");
                }*/
                returnedPurchaseModel.update(returnedPurchaseEntityExt);
                break;
            case CONTRACT_OUTSTOCK:
                ContractEntityExt contractEntityExt = contractModel.getByKey(refId,corpid);
                if (Objects.isNull(contractEntityExt)) {
                    return;
                }
                // 销售出库时更新合同成本
                ContractUpdateWhenOutstockDTO contractUpdateWhenOutstockDTO = new ContractUpdateWhenOutstockDTO();
                contractUpdateWhenOutstockDTO.setCorpid(corpid);
                contractUpdateWhenOutstockDTO.setNewData(data);
                contractUpdateWhenOutstockDTO.setNewPaasFormDataEntity(paasFormDataEntity);
                contractHelp.updateContractCostWhenOutstock(contractUpdateWhenOutstockDTO, contractEntityExt);

                String expressName = data.getString(ContractOutstockEnum.EXPRESS_NAME.getAttr());
                String expressNo = data.getString(ContractOutstockEnum.EXPRESS_NO.getAttr());
                JSONObject contractTargetData = contractEntityExt.getData();
                JSONObject contractData = new JSONObject();
                //合同成本相关
                // fix bug 38739:  上面 updateContractCostWhenOutstock 对出库之后的合同成本的相关字段进行了计算，但是没有把结果塞到下面contractData里面，导致合同成本，毛利那些指标没更新
                String estimateCostAttr = ContractEnum.ESTIMATE_COST.getAttr();
                String realCostAttr = ContractEnum.REAL_COST.getAttr();
                String contractCostAttr = ContractEnum.CONTRACT_COST.getAttr();
                String grossProfit = ContractEnum.GROSS_PROFIT.getAttr();
                String cashProfit = ContractEnum.CASH_PROFIT.getAttr();
                String grossProfitRateAttr = ContractEnum.GROSS_PROFIT_RATE.getAttr();
                String cashProfitRateAttr = ContractEnum.CASH_PROFIT_RATE.getAttr();

                contractData.put(estimateCostAttr,contractTargetData.get(estimateCostAttr));
                contractData.put(realCostAttr,contractTargetData.get(realCostAttr));
                contractData.put(contractCostAttr,contractTargetData.get(contractCostAttr));
                contractData.put(grossProfit,contractTargetData.get(grossProfit));
                contractData.put(cashProfit,contractTargetData.get(cashProfit));
                contractData.put(grossProfitRateAttr,contractTargetData.get(grossProfitRateAttr));
                contractData.put(cashProfitRateAttr,contractTargetData.get(cashProfitRateAttr));

                //其他
                if (Objects.nonNull(expressName)) {
                    contractData.put(ContractEnum.EXPRESS_NAME.getAttr(), expressName);
                }
                if (Objects.nonNull(expressNo)) {
                    contractData.put(ContractEnum.EXPRESS_NO.getAttr(), expressNo);
                }
                if (Objects.isNull(distributorMark) || Objects.equals(distributorMark, DistributorMarkEnum.OTHER.getCode())) {
                    contractData.put(ContractEnum.EXPRESS_STATUS.getAttr(), ExpressStatusEnum.SHIPPED.getCode());
                }
                List<Long> contractIds=new ArrayList<>();
                allOutBound = contractHelp.judgeContractAllOutBound(outstockId,refId,corpid,productSavePojoList);
                if (allOutBound){
                    contractData.put(ContractEnum.ALL_OUT_BOUND.getAttr(), AllOutBoundEnum.ALL_OUT.getCode());
                    contractData.put(ContractEnum.SHIP_STATUS.getAttr(), ShipStatusEnum.SHIPPED.getCode());
                }else {
                    contractData.put(ContractEnum.ALL_OUT_BOUND.getAttr(), AllOutBoundEnum.NON_OUT.getCode());
                    contractData.put(ContractEnum.SHIP_STATUS.getAttr(), ShipStatusEnum.DELIVERED.getCode());
                }
                JSONArray outstockIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(contractTargetData,ContractEnum.OUTSTOCK_ID.getAttr(),new JSONArray());
                outstockIdList.add(outstockId);
                contractData.put(ContractEnum.OUTSTOCK_ID.getAttr(), outstockIdList);
                List<ContractUpdateDTO> contractUpdateList = new ArrayList<>();
                ContractUpdateDTO contractUpdateDTO = new ContractUpdateDTO();
                contractUpdateDTO.setId(contractEntityExt.getId());
                contractUpdateDTO.setData(contractData);
                contractUpdateList.add(contractUpdateDTO);
                contractIds.add(contractEntityExt.getId());
                List<UpdateDataEntity> updateList = new ArrayList<>();
                contractUpdateList.forEach(item -> updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid)));
                if (!updateList.isEmpty()) {
                    contractModel.updateBatchImmediately(updateList, corpid);
                    //更新待出库状态
                    contractProductModel.updateWaitOutStatusById(contractIds,corpid, WaitOutStockStatusEnum.UNUSUAL.getCode(),WaitOutStockStatusEnum.UNUSUAL.getCode());
                }
                break;
            case INVENTORY_OUTSTOCK:
                paasFormDataEntityExt = inventoryModel.getByKey(refId,corpid);
                if (Objects.isNull(paasFormDataEntityExt)) {
                    return;
                }
                InventoryEntityExt inventoryEntityExt = new InventoryEntityExt();
                BeanUtil.copyProperties(paasFormDataEntityExt,inventoryEntityExt);
                JSONObject inventoryData = inventoryEntityExt.getData();
                inventoryData.put(InventoryEnum.OUTSTOCK_ID.getAttr(), outstockId);
                Integer ifProfit = inventoryData.getInteger(InventoryEnum.IF_PROFIT.getAttr());
                Long instockId = inventoryData.getLong(InventoryEnum.INSTOCK_ID.getAttr());
                inventoryData.put(InventoryEnum.INVENTORY_STATUS.getAttr(), InventoryNewStatusEnum.UNFINISHED.getCode());
                //不需要审批状态下直接改对应单据状态
                if (Objects.equals(0, ifProfit)) {
                    //没有盘赢直接改状态为已出入库
                    inventoryData.put(InventoryEnum.STATUS.getAttr(), InventoryStatusEnum.ALREADY_OUT_INSTOCK.getCode());
                    inventoryData.put(InventoryEnum.INVENTORY_STATUS.getAttr(), InventoryNewStatusEnum.FINISHED.getCode());
                } else if (Objects.equals(1, ifProfit) && !Objects.equals(0L, instockId)) {
                    //有盘赢但已入过库则改状态为已出入库
                    inventoryData.put(InventoryEnum.STATUS.getAttr(), InventoryStatusEnum.ALREADY_OUT_INSTOCK.getCode());
                    inventoryData.put(InventoryEnum.INVENTORY_STATUS.getAttr(), InventoryNewStatusEnum.FINISHED.getCode());
                }
                inventoryModel.update(inventoryEntityExt);
                break;
            case TRANSFER_OUTSTOCK:
                paasFormDataEntityExt = transferModel.getByKey(refId,corpid);
                if (Objects.isNull(paasFormDataEntityExt)) {
                    return;
                }
                TransferEntityExt transferEntityExt = new TransferEntityExt();
                BeanUtil.copyProperties(paasFormDataEntityExt,transferEntityExt);
                JSONObject transferData = transferEntityExt.getData();
                transferData.put(TransferEnum.OUTSTOCK_ID.getAttr(), outstockId);
                instockId = transferData.getLong(TransferEnum.INSTOCK_ID.getAttr());
                transferData.put(TransferEnum.OUTSTOCK_ID.getAttr(), outstockId);
                transferData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNRECEIVED.getCode());
                if (Objects.nonNull(instockId) && instockId != 0) {
                    transferData.put(TransferEnum.STATUS.getAttr(), 2);
                }
                List<Long> transferIds = new ArrayList<>();
                transferIds.add(refId);
                transferHelp.updateTransferOutstockNum(transferIds,corpid,productSavePojoList,true);
                transferModel.update(transferEntityExt);
                break;
            case WORK_ORDER_OUTSTOCK:
                WorkOrderEntity workOrderEntity = workOrderModel.getByKey(refId,corpid);
                if (Objects.isNull(workOrderEntity) || Objects.equals(workOrderEntity.getDel(), DelEnum.DELETE.getDel())) {
                    return;
                }
                JSONObject workOrderEntityData = workOrderEntity.getData();
                Integer shipStatus = workOrderHelp.judgeWorkOrderAllOutBound(outstockId,refId,corpid,productSavePojoList);
                workOrderEntityData.put(WorkOrderEnum.SHIP_STATUS.getAttr(), shipStatus);
                if (WorkOrderShipStatusEnum.SHIPPED.getCode().equals(shipStatus)) {
                    workOrderEntity.setAllOutbound(AllOutBoundEnum.ALL_OUT.getCode());
                } else {
                    workOrderEntity.setAllOutbound(AllOutBoundEnum.NON_OUT.getCode());
                }
                workOrderModel.update(workOrderEntity);
                break;
            case MATERIEL_OUTSTOCK:
                paasFormDataEntityExt = productionOrderModel.getByKey(refId,corpid);
                if (Objects.isNull(paasFormDataEntityExt)) {
                    return;
                }
                JSONObject updateData = new JSONObject();
                JSONObject productionOrderData = paasFormDataEntityExt.getData();
                outstockIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(productionOrderData,ProductionOrderEnum.OUTSTOCK_ID.getAttr(),new JSONArray());
                outstockIdList.add(outstockId);

                updateData.put(ProductionOrderEnum.OUTSTOCK_ID.getAttr(), outstockIdList);
                allOutBound = productionOrderHelp.judgeProductionOrderAllOutBound(outstockId,refId,corpid,productSavePojoList);
                updateData.put(ProductionOrderEnum.HAS_RETURNED_MATERIEL.getAttr(), AllOutBoundEnum.ALL_OUT.getCode());
                if (allOutBound){
                    updateData.put(ProductionOrderEnum.ALL_OUTBOUND.getAttr(), AllOutBoundEnum.ALL_OUT.getCode());
                }else {
                    updateData.put(ProductionOrderEnum.ALL_OUTBOUND.getAttr(), AllOutBoundEnum.NON_OUT.getCode());
                }
                List<UpdateDataEntity> list = new ArrayList<>();
                list.add(ExplainUtil.getUpdateData(paasFormDataEntityExt.getId(), updateData, corpid));
                productionOrderModel.updateBatch(list, corpid);
                break;
            default:
                break;
        }
    }


    public Map<Long, ProductStockUpdateEntity> addUpdateStock(List<OutstockProductEntity> outstockProductList, String corpid) throws XbbException {
        Map<Long,ProductStockUpdateEntity> productUpdateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, ProductStockUpdateEntity> warehouseProductUpdateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, ProductStockUpdateEntity> batchProductUpdateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (OutstockProductEntity entity : outstockProductList){
            Double amendNum = entity.getProductNum() == null ? 0D : entity.getProductNum();
            //库存减少业务
            amendNum = -amendNum;
            Double amendCost = entity.getCost() == null ? 0D : entity.getCost();
            Long productId = entity.getProductId();
            String warehouseKey = productId + "_" + entity.getWarehouseId();
            // 全仓库存数据
            String allWarehouseKey = productId + "_" + 0;
            //分仓数量
            if (warehouseProductUpdateMap.containsKey(warehouseKey)){
                ProductStockUpdateEntity productStockUpdateEntity = warehouseProductUpdateMap.get(warehouseKey);
                productStockUpdateEntity.updateStock(amendNum,amendCost);
                warehouseProductUpdateMap.put(warehouseKey,productStockUpdateEntity);
            }else {
                ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(warehouseKey,amendNum,amendCost);
                warehouseProductUpdateMap.put(warehouseKey,productStockUpdateEntity);
            }
            //总仓数量
            if (warehouseProductUpdateMap.containsKey(allWarehouseKey)){
                ProductStockUpdateEntity productStockUpdateEntity = warehouseProductUpdateMap.get(allWarehouseKey);
                productStockUpdateEntity.updateStock(amendNum,amendCost);
                warehouseProductUpdateMap.put(allWarehouseKey,productStockUpdateEntity);
            }else {
                ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(allWarehouseKey,amendNum,amendCost);
                warehouseProductUpdateMap.put(allWarehouseKey,productStockUpdateEntity);
            }
            //批次数量
            if (StringUtil.isNotEmpty(entity.getBatch())) {
                String batchKey = BatchKeyHelp.getBatchKey(productId, entity.getWarehouseId(), entity.getBatch(), entity.getProduceDate(), entity.getGuaranteePeriod());
                if (batchProductUpdateMap.containsKey(batchKey)){
                    ProductStockUpdateEntity productStockUpdateEntity = batchProductUpdateMap.get(batchKey);
                    productStockUpdateEntity.updateStock(amendNum,amendCost);
                    batchProductUpdateMap.put(batchKey,productStockUpdateEntity);
                }else {
                    ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(batchKey,amendNum,amendCost);
                    batchProductUpdateMap.put(batchKey,productStockUpdateEntity);
                }
            }
            //产品
            if (productUpdateMap.containsKey(entity.getProductId())){
                ProductStockUpdateEntity productStockUpdateEntity = productUpdateMap.get(entity.getProductId());
                productStockUpdateEntity.updateStock(amendNum,amendCost);
                productUpdateMap.put(entity.getProductId(),productStockUpdateEntity);
            }else {
                ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(productId,amendNum,amendCost);
                productUpdateMap.put(entity.getProductId(),productStockUpdateEntity);
            }
        }
        productStockModel.updateStockDB(batchProductUpdateMap.keySet(), batchProductUpdateMap.values(),corpid);
        productWarehouseModel.updateStockDB(warehouseProductUpdateMap.keySet(), warehouseProductUpdateMap.values(),corpid, false);
        return productUpdateMap;
    }
}
